home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Modules / BackSpaceModules / Source / CreepyFace / CreepyFaceView.m < prev    next >
Text File  |  1994-03-23  |  8KB  |  416 lines

  1. #import "CreepyFaceView.h"
  2. #import <math.h>
  3. #import "CFWireFrame.h"
  4. #import <sys/dir.h>
  5. #import <sys/types.h>
  6. #import <objc/NXBundle.h>
  7.  
  8. @class CFWireFrame;
  9.  
  10. // this code is copyright Darcy Brockbank, 1993
  11. //
  12. // You may freely reuse and distribute this code in any way shape or
  13. // form, provided that this notice stays intact.
  14. //
  15. // darcy@hasc.ca, samurai@cs.mcgill.ca
  16. //
  17. // StefView was implemented out of WorldSpaceView and retains some of the
  18. // movement properties...
  19. //
  20. // The code for WorldSpaceView was written by Sam Streeper at CreepyFace, I think,
  21. // and there were two other contributors, but I can't find their names in the
  22. // source for it.
  23. //
  24. // CreepyFaceView shows a simple (ha!) spinning CreepyFace, in full 3D. The 3D code
  25. // came from an app I wrote a long time ago called "CFWireFrame", and so the code
  26. // is pretty scary. As well, this thing is only a quick hack, though a nice one.
  27. //
  28. // This thing has room for improvement, and if you do so, send me a copy!
  29. //
  30. // - darcy
  31.  
  32. @implementation CreepyFaceView
  33.  
  34.  
  35. #define X_PERIOD 15000.0
  36. #define Y_PERIOD 12000.0
  37. #define DEFAULT_FPS 10
  38. #define PI 3.1415926535
  39. #define SIZE 256.0
  40. #define MAX_IMAGE_WIDTH SIZE
  41. #define MAX_IMAGE_HEIGHT SIZE
  42. #define MAX_X_SPEED (26)
  43. #define MAX_Y_SPEED (26)
  44. #define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
  45. #define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
  46. #define PRINT(a) printf(a)
  47.  
  48. #define MINX 0.0
  49. #define MINY 0.0
  50.  
  51.  
  52. #define ZOOM 680.0
  53.  
  54. - takeSpot:(float)x:(float)y;
  55. {
  56.     [self draw];
  57.     return self;
  58. }
  59.  
  60. - takeSnapshot;
  61. {
  62.     return self;
  63. }
  64.  
  65. - oneStep
  66. {
  67.     NXRect black = {0,0,0,0};
  68.     NXRect ballRect;
  69.     BRECT new;
  70.     static float xdelt = 2.0;
  71.     static float ydelt = 2.0;
  72.     int changed = 0;
  73.     
  74.     then = now;
  75.     now = currentTimeInMs();
  76.  
  77.     xpos += xdelt;
  78.     if (xpos<MINX) {
  79.         xpos = MINX;
  80.         xdelt*=-1.0;
  81.         changed=1;
  82.     } else if (xpos>maxCoord.x){
  83.         xpos = maxCoord.x;
  84.         xdelt*=-1.0;
  85.         changed=1;
  86.     }
  87.     ypos += ydelt;
  88.     if (ypos<MINY) {
  89.         ypos = MINY;
  90.         ydelt*=-1.0;
  91.         changed=1;
  92.     } else if (ypos>maxCoord.y){
  93.         ypos = maxCoord.y;
  94.         ydelt*=-1.0;
  95.         changed=1;
  96.     }
  97.  
  98.     if (changed){
  99. #if 0
  100.         Axis flip[3]={y,y,y};
  101.         Direction dir[2]={positive,positive};
  102. #else
  103.         Axis flip[3]={y,z,x};
  104.         Direction dir[2]={positive,negative};
  105. #endif
  106.  
  107.         axis = flip[axis];
  108.         spin = dir[spin];
  109.     }
  110.     
  111.     new.l = floor(xpos);
  112.     new.b = floor(ypos);
  113.     new.r = new.l + imageSize.width;
  114.     new.t = new.b + imageSize.height;
  115.  
  116.     
  117.     ballRect.origin.x = 0;
  118.     ballRect.origin.y = 0;
  119.     ballRect.size.width = imageSize.width;
  120.     ballRect.size.height = imageSize.height;
  121.     
  122.     redrawTo.x = MIN(new.l, old.l);
  123.     redrawTo.y = MIN(new.b, old.b);
  124.  
  125.     redraw.origin.x = 0;
  126.     redraw.origin.y = 0;
  127.     redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
  128.     redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
  129.     
  130.     black.size= redraw.size;
  131.  
  132.  
  133.     [buffer lockFocus];
  134.     PSsetgray(0);
  135.     NXRectFill(&black);
  136.  
  137.     [self draw];
  138.     
  139.     ballTo.x = new.l - redrawTo.x;
  140.     ballTo.y = new.b - redrawTo.y;
  141.  
  142.     [buffer unlockFocus];
  143.     [buffer composite:NX_COPY toPoint:&redrawTo];
  144.     old = new;
  145.     return self;
  146. }
  147.  
  148.  
  149.  
  150. - initFrame:(const NXRect *)frameRect
  151. {
  152.     const char *animSpeed;
  153.     NXRect black = {0, 0, SIZE, SIZE };
  154.  
  155.     imageSize = black.size;
  156.     [super initFrame:frameRect];
  157.     [self allocateGState];        // For faster lock/unlockFocus
  158.     [self setClipping:NO];        // even faster...
  159.  
  160.     PSsetlinewidth(0.15);
  161.     backgroundColour=NX_COLORBLACK;
  162.     worldOrigin.x=0.0;
  163.     worldOrigin.y=0.0;
  164.     worldOrigin.z=0.0;
  165.     translationRate = 3.0;
  166.     currentZoom=ZOOM;
  167.     list = [[List alloc] init];
  168.     axis = y;
  169.     spin = positive;
  170.     
  171.     buffer = [[NXImage alloc] initSize:&black.size];
  172.  
  173.     if ([buffer lockFocus])
  174.     {
  175.         PSsetgray(0);
  176.         NXRectFill(&black);
  177.         [buffer unlockFocus];
  178.     }
  179.     animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed");
  180.     if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS;
  181.     else framesPerSecond = atoi(animSpeed);
  182.     nextRotationTime = 0;
  183.     [self newViewSize];
  184.     return self;
  185. }
  186.  
  187. - sizeTo:(NXCoord)width :(NXCoord)height
  188. {
  189.     [super sizeTo:width :height];
  190.     [self newViewSize];
  191.     return self;
  192. }
  193.  
  194. - newViewSize
  195. {
  196.     //this is called every time View size changes
  197.     NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
  198.  
  199.     then = now = currentTimeInMs();
  200.  
  201.     if (oldSize.width == bounds.size.width &&
  202.             oldSize.height == bounds.size.height)
  203.         return self;
  204.     else
  205.     {
  206.         oldSize.width = bounds.size.width;
  207.         oldSize.height = bounds.size.height;
  208.     }
  209.     
  210.     maxCoord.x = bounds.size.width - imageSize.width - MINX;
  211.     maxCoord.y = bounds.size.height - imageSize.height - MINY;
  212.     if (maxCoord.x < 0) maxCoord.x = 0;
  213.     if (maxCoord.y < 0) maxCoord.y = 0;
  214.  
  215.  
  216.     old.l = old.r = maxCoord.x/2 + MINX;
  217.     old.b = old.t = maxCoord.y/2 + MINY;
  218.     ballTo.x = ballTo.y = 0;
  219.  
  220.     if ([buffer lockFocus])
  221.     {
  222.         PSsetgray(0);
  223.         NXRectFill(&black);
  224.         [buffer unlockFocus];
  225.     }
  226.  
  227.     return self;
  228. }
  229.  
  230. - (const char *)windowTitle
  231. {
  232.     return "CreepyFaceView";
  233. }
  234.  
  235.  
  236.  
  237. - inspector:sender
  238. {
  239.     char buf[MAXPATHLEN];
  240.     if (!sharedInspectorPanel){
  241.         sprintf(buf,"%s/CreepyFaceView.nib",[sender moduleDirectory:"CreepyFace"]);
  242.         [NXApp loadNibFile:buf owner:self withNames:NO];
  243.         [self loadDir:[sender moduleDirectory:"CreepyFace"]];
  244.     }
  245.     return sharedInspectorPanel;
  246. }
  247.  
  248. - tryToChangeCentre
  249. {
  250.     id object=[self firstObject];
  251.     if (object) {
  252.         [object getCentre:&curOrigin.x:&curOrigin.y:&curOrigin.z];
  253.     } else {
  254.         curOrigin.x = curOrigin.y = curOrigin.z = 0.0;
  255.     }
  256.     return self;
  257. }
  258.  
  259. - firstObject
  260. {
  261.     return [list objectAt:0];
  262. }
  263.  
  264. - free 
  265. {
  266.     [list free];
  267.     return [super free];
  268. }
  269.     
  270. - (const char *)world;
  271. {
  272.     return "CreepyFace.world";
  273. }
  274.  
  275. - loadDir:(const char *)dir
  276. {
  277.         char world[MAXPATHLEN+1];
  278.     sprintf(world,"%s/%s",dir,[self world]);
  279.     [self loadWorld:world];
  280.     [self tryToChangeCentre];
  281.     [self display];
  282.     return self;
  283. }
  284.  
  285. - loadWorld:(const char *)world
  286. {
  287.     DIR *dirp;
  288.     id newFrame;
  289.     struct direct *dp;
  290.     char *tail;
  291.     char temp[1024];
  292.     
  293.     
  294.     dirp=opendir(world);
  295.     if (!dirp) {
  296.         NXRunAlertPanel("Directory Error", "Can't read directory: %s","OK",0,0,world);
  297.     } else {
  298.         for(dp=readdir(dirp);dp!=NULL;dp=readdir(dirp)){
  299.             if ((tail=(rindex(dp->d_name,'.')))!=NULL){
  300.                 if (strcmp((tail+1),"wireframe")==0){
  301.                     sprintf(temp,"%s/%s",world,dp->d_name);
  302.                     newFrame = [[CFWireFrame alloc] init];
  303.                     [newFrame makeCFWireFrame:temp];
  304.                     [self addThisObject:newFrame];
  305.                     [newFrame translate:negative alongAxis:z atRate:1200];
  306.                 }
  307.                 if (strcmp((tail+1),"wireframeb")==0){
  308.                     sprintf(temp,"%s/%s",world,dp->d_name);
  309.                     newFrame = [[CFWireFrame alloc] init];
  310.                     [newFrame readBinaryCodeFrom:temp];
  311.                     [self addThisObject:newFrame];
  312.                     [newFrame translate:negative alongAxis:z atRate:1200];
  313.                 }
  314.             }
  315.         }            
  316.     }
  317.     return self;
  318. }
  319.  
  320. - setTranslationRate:sender;
  321. {
  322.     translationRate=[sender floatValue];
  323.     return self;
  324. }
  325.  
  326.  
  327. - (int)numberOfObjects
  328. {
  329.     return [list count];
  330. }
  331.  
  332. - addThisObject:anObject
  333. {
  334.     [list addObject:anObject];
  335.     return self;
  336. }
  337.  
  338. - setZoom: sender
  339. {
  340.     currentZoom=[sender floatValue];
  341.     [self display];
  342.     return self;
  343. }
  344.  
  345.  
  346. - draw;
  347. {
  348.     int i,count = [list count] ;
  349.  
  350.     for (i=0;i<count;i++){
  351.         id wireFrame = [list objectAt:i];
  352.         [wireFrame rotate:spin aroundAxis:axis atOrigin:curOrigin];
  353.         [wireFrame drawYourself:currentZoom
  354.             centeredOn:imageSize.width/2.0 :imageSize.height/2.0];
  355.     }
  356.     return self;
  357. }
  358.  
  359. - translate:(Direction)dir alongAxis:(Axis)a atRate:(float)rate
  360.     int i,count = [list count];
  361.     for (i=0;i<count;i++){
  362.         [[list objectAt:i] translate:dir
  363.                     alongAxis:a
  364.                     atRate:rate];
  365.     }
  366.     [self tryToChangeCentre];
  367.     return self;
  368. }
  369.  
  370.  
  371. - rotate:(Direction)dir aroundAxis:(Axis)a atOrigin:(Origin)orig
  372. {
  373.     int i,count = [list count];
  374.  
  375.     for (i=0;i<count;i++){
  376.         [[list objectAt:i] rotate:dir
  377.                     aroundAxis:a
  378.                     atOrigin:orig];
  379.     }
  380.     return self;
  381. }
  382.  
  383. - rotatey:sender;
  384. {
  385.     [self rotate:negative aroundAxis:y atOrigin:curOrigin];
  386.     return self;
  387. }
  388. - rotateY:sender;
  389. {
  390.     [self rotate:positive aroundAxis:y atOrigin:curOrigin];
  391.     return self;
  392. }
  393. - rotatez:sender;
  394. {
  395.     [self rotate:negative aroundAxis:z atOrigin:curOrigin];
  396.     return self;
  397. }
  398. - rotateZ:sender;
  399. {
  400.     [self rotate:positive aroundAxis:z atOrigin:curOrigin];
  401.     return self;
  402. }
  403. - rotatex:sender;
  404. {
  405.     [self rotate:negative aroundAxis:x atOrigin:curOrigin];
  406.     return self;
  407. }
  408. - rotateX:sender;
  409. {
  410.     [self rotate:positive aroundAxis:x atOrigin:curOrigin];
  411.     return self;
  412. }
  413.     
  414. @end
  415.